/**
  ******************************************************************************
  * @file    Console.c 

  ******************************************************************************
  */ 

/* Includes ------------------------------------------------------------------*/
#include "Console.h"
#include "system_stm32f10x.h"
#include "stm32f10x.h"
#include "SystemConfig.h"
#include "stm32f10x_it.h"
#include "stdlib.h"
#include "string.h"
#include "Queue.h"
#include "memory.h"
#include "config.h"

/** @addtogroup STM32F10x_StdPeriph_Examples
  * @{
  */

/** @addtogroup SysTick
  * @{
  */ 

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static volatile unsigned long TimingDelay;

/* Private function prototypes -----------------------------------------------*/
void UART_IRQ_Tx(void);
void UART_IRQ_Rx(void);

/* Private functions ---------------------------------------------------------*/

//fenris 20110128
/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */

QBuf ConRxBuf;
QBuf ConTxBuf;

void Console_Init(void)
{    
    NVIC_InitTypeDef		NVIC_InitStructure;
	GPIO_InitTypeDef		GPIO_InitStructure;
	USART_InitTypeDef		USART_InitStructure;
	USART_ClockInitTypeDef	USART_ClockInitStructure;
	EXTI_InitTypeDef		EXTI_InitStructure;
	

	/* clock setting */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

	/* GPIO Setting */
	/* PA9: UART TX */
	GPIO_InitStructure.GPIO_Pin		= GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode	= GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed	= GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	/* PA10: UART RX */
	GPIO_InitStructure.GPIO_Pin		= GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode	= GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	/* NVIC Setting */
	NVIC_InitStructure.NVIC_IRQChannel				= USART3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority	= IRQ_USART1;
	NVIC_InitStructure.NVIC_IRQChannelCmd			= ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel				= EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority	= IRQ_EXTI_15_10;
	NVIC_InitStructure.NVIC_IRQChannelCmd			= ENABLE;
	NVIC_Init(&NVIC_InitStructure);
    

	/* EXTI Setting */      
	EXTI_ClearITPendingBit(EXTI_Line12);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource12);
	EXTI_InitStructure.EXTI_Mode	= EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Line	= EXTI_Line12;
	EXTI_InitStructure.EXTI_Trigger	= EXTI_Trigger_Rising_Falling;
	EXTI_InitStructure.EXTI_LineCmd	= ENABLE;
	EXTI_Init(&EXTI_InitStructure);
	EXTI_ClearITPendingBit(EXTI_Line12);
    

	/* USART3 Setting */
	USART_InitStructure.USART_BaudRate		= 115200;	//57600;    //UART_BAUDRATE;
	USART_InitStructure.USART_WordLength	= USART_WordLength_8b;
	USART_InitStructure.USART_StopBits		= USART_StopBits_1;
	USART_InitStructure.USART_Parity		= USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode			= USART_Mode_Rx | USART_Mode_Tx;
	
	USART_ClockInitStructure.USART_Clock		= USART_Clock_Disable;
	USART_ClockInitStructure.USART_CPOL			= USART_CPOL_Low;
	USART_ClockInitStructure.USART_CPHA			= USART_CPHA_2Edge;
	USART_ClockInitStructure.USART_LastBit		= USART_LastBit_Disable;
	
	
	USART_Init(USART3, &USART_InitStructure);
	USART_ClockInit(USART3, &USART_ClockInitStructure);
    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
	USART_Cmd(USART3, ENABLE);
    
    QBuf_Init(&ConTxBuf, pConsoleTxData, CONSOLE_TX_SIZE);
	QBuf_Init(&ConRxBuf, pConsoleRxData, CONSOLE_RX_SIZE);
	*pFlag_console_tx_busy = 0;
}

void UART_IRQ_Tx(void)
{
    char buf;

	if (ConTxBuf.use != 0)
	{
		QBuf_Read(&ConTxBuf, &buf, 1);
		USART_SendData(USART3, buf);
	}
	else
	{
		USART_ITConfig(USART3, USART_IT_TXE, DISABLE);
		*pFlag_console_tx_busy = 0;
	}
}

void UART_IRQ_Rx(void)
{
	char buf;

	buf = USART_ReceiveData(USART3);
	QBuf_Write(&ConRxBuf, &buf, 1);
}

/*
 * ----------------------------------------------------------------------------
 * Description: Debug port message 
 * Argument(s): message buffer point
 * Return(s)  : None
 * Note(s)    : Max buffer is 256
 * ----------------------------------------------------------------------------
 */
void Console_Out256(char *buf)
{
	unsigned long buflen;
	buflen=strlen(buf);
	if (buflen>256)
		buflen=256;
	Console_Write(buf,buflen);
}

void Console_Write(char *buf, unsigned short count)
{
	char *tmp;
	unsigned short remain;
	unsigned long wait=0xffffffff;
	unsigned char ConsoleRetry=0;
	tmp = buf;
	
	do
	{
	
	WRITE:  
	  
		remain = ConTxBuf.len - ConTxBuf.use;
		
		if(remain==0)
		{		
		   if(ConsoleRetry==0)
		   {
		   		wait=Get_Systick();
				ConsoleRetry++;
		   }


			if((Get_Systick()-wait)>25) //wait 250ms
			{	
			  	ConsoleRetry++;
				goto ENABLE;
			}
			else	  	
				goto WRITE;
		}
		
		if (count < remain)
		{
			remain = count;
		}
		count -= remain;
		
		QBuf_Write(&ConTxBuf, tmp, remain);

		tmp += remain;

		if (*pFlag_console_tx_busy == 0)
		{
	ENABLE:			  
			*pFlag_console_tx_busy = 1;


		    USART_ITConfig(USART3, USART_IT_TXE, ENABLE);

		}

	} while (count != 0);	/* put all input to gTxQBuf */
}

unsigned short Console_Read(char *buf, unsigned short count)
{
	if (count > ConRxBuf.use)
	{
		count = ConRxBuf.use;
	}
	QBuf_Read(&ConRxBuf, buf, count);
	return count;
}